﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Comdiv.QWeb.Binding;
using Comdiv.QWeb.Factory;
using NUnit.Framework;

namespace Comdiv.QWeb.Test.Configuraiton
{
	[TestFixture]
	public class factory_test
	{
        [Render("all")]
        public class allrender:IRender {
            public bool NeedResult {
                get { return false; }
            }

            public void Render(QWebContext context) {
                throw new NotImplementedException();
            }

            public void RenderError(Exception error, QWebContext context) {
                throw new NotImplementedException();
            }
        }

        [Action("test.all")]
        public class allaction:IAction {
            public object Process(QWebContext context) {
                throw new NotImplementedException();
            }
        }

        [Test]
        public void test_all_actions_types_works() {
            CollectionAssert.Contains(new QWebFactory().GetAllActionTypes(),typeof(allaction));   
        }

        [Test]
        public void test_all_renders_types_works() {
            CollectionAssert.Contains(new QWebFactory().GetAllRenderTypes(), typeof(allrender));
        }

        [Test]
        public void test_all_actions_works()
        {
            Assert.NotNull(new QWebFactory().GetAllActions().FirstOrDefault(x=>x.Name=="test.all"));
        }

        [Test]
        public void test_all_renders_works()
        {
            Assert.NotNull(new QWebFactory().GetAllRenders().FirstOrDefault(x => x.Name == "all"));
        }


		[Render("sample")]
		public class sampleRender:IRender {
			public bool NeedResult {
				get { return false; }
			}

			public void Render(QWebContext context) {
				context.Output.Write("sample");
			}

			public void RenderError(Exception error, QWebContext context) {
				throw new NotImplementedException();
			}
		}
        public class bindableAction : IAction {
            public object Process(QWebContext context) {
                return null;
            }
        }

        public class notBindableAction : IAction
        {
            public object Process(QWebContext context) {
                return null;
            }
        }

        public class customBinder : IActionBinder {
            public static bool called;

            public bool IsBindable(Type actionType) {
                if(typeof(bindableAction)==actionType) return true;
                return false;
            }

            public void Bind(ActionDescriptor action, QWebContext context) {
                called = true;
            }
        }

        [Test]
        public void Register_Action_Works() {
            var f = new QWebFactory();
            f.RegisterAction<bindableAction>("t.b");
            var b = f.GetAction("t.b");
            Assert.NotNull(b);

            f.RegisterAction<bindableAction>("test.int");
            b = f.GetAction("test.int");
            Assert.NotNull(b);
        }

        [Test]
        public void validTypeDescriptorsProvidedWithBindings() {
            var f = new QWebFactory();
            f.Registry.RegisterService<IActionBinder,customBinder>();
            f.RegisterAction<bindableAction>("t.b");
            f.RegisterAction<notBindableAction>("t.nb");
            var b = f.GetAction("t.b");
            Assert.NotNull(b.TypeDescriptor);
            Assert.True(b.TypeDescriptor.SupportsBind);
            Assert.AreEqual(typeof(customBinder),b.TypeDescriptor.GetBinderType());
            var nb = f.GetAction("t.nb");
            Assert.NotNull(nb.TypeDescriptor);
            Assert.False(nb.TypeDescriptor.SupportsBind);
            Assert.Null(nb.TypeDescriptor.GetBinderType());
        }

        [Test]
        public void binderCalled()
        {
            var f = new QWebFactory();
            f.Registry.RegisterService<IActionBinder, customBinder>();
            f.RegisterAction<bindableAction>("t.b");
            var b = f.GetAction("t.b");
            customBinder.called = false;
            b.Process(null);
            Assert.True(customBinder.called);
        }

		[Test]
		public void can_found_custom_render_engine() {
			TextWriter sw = new StringWriter();
			var result = new QWebHandler().ProcessRequest(new QWebContext("http://localhost/qweb/echo.sample.qweb"){Output = sw});
			Assert.AreEqual("sample",sw.ToString());
		}



        [Test]
        public void can_found_default_binder() {
            var f = new QWebFactory();
            var binders = f.GetBinders();
            Assert.NotNull(binders);
            Assert.AreNotEqual(0,binders.Count());
            Assert.IsInstanceOf<DefaultActionBinder>(binders.First());
        }


		[Test]
		public void if_not_found_action_throws_exception()
		{
			Assert.Throws<ActionNotFoundException>(()=>new QWebFactory().GetAction(new QWebContext("http://localhost/qweb/notfound.qweb")));
		}

		[Test]
		public void double_not_found_processed_from_cache_COVER_PROPOSE()
		{
			
		}

		[Test]
		public void if_not_found_render_throws_exception()
		{
			Assert.Throws<RenderNotFoundException>(() => new QWebFactory().GetRender(new QWebContext("http://localhost/qweb/echo.notfound.qweb")));
		}
	}
}
